#pragma once
#include "stdafx.h"
#include "Element.h"
#include "StreamPage.h"
#include "BufferConstraint.h"
#include <boost/shared_ptr.hpp>
#include <map>
#include "AbstractBuffer.h"
/* a buffer to saves the queue information 
* elements are saved in this buffer
* this buffer acts as a queue, elements comes first will go out first.
*/
class QueueBuffer : public AbstractBuffer
{
private:
	MemoryPosition freePositionHead;
	std::queue<MemoryPosition> elementQueue;
	int elementNumber; // how many elements are buffered

public:
	QueueBuffer(void)
	{

		this->freePositionHead.pageIndex=0;
		this->freePositionHead.chunkIndex=0;

		this->elementNumber = 0;
	}
	~QueueBuffer(void){}
	inline void enqueue(Element& element)
	{
		bool bl = isFull();
		assert(bl==false);
		if(bl==true)
		{
			std::cout<<"memory not enough"<<std::endl;
			exit(0);
		}
		this->setElementByMemoryPosition(element,freePositionHead);
		this->elementQueue.push(freePositionHead);
		this->getNextPosition(freePositionHead,freePositionHead);
		this->elementNumber++;
	}
	inline void dequeue(Element& element)
	{
		assert(this->elementNumber>0);
		assert(elementQueue.size()>0);
		MemoryPosition dequePosition = this->elementQueue.front();
		this->getElementByMemoryPosition(element,dequePosition);
		this->elementNumber--;

		this->setNextPosition(dequePosition,freePositionHead);
		freePositionHead = dequePosition;
		this->elementQueue.pop();
	}
	inline void dequeue(void)
	{
		assert(this->elementNumber>0);
		assert(elementQueue.size()>0);
		MemoryPosition dequePosition = this->elementQueue.front();
		this->elementNumber--;

		this->setNextPosition(dequePosition,freePositionHead);
		freePositionHead = dequePosition;
		this->elementQueue.pop();
	}
	inline void peek(Element& element)
	{
		assert(this->elementNumber>0);

		MemoryPosition dequePosition = this->elementQueue.front();
		this->getElementByMemoryPosition(element,dequePosition);

	}

	inline bool isFull(void)
	{
		bool ret;
		if(!isValidMemoryPosition(freePositionHead))
		{
			ret = this->allocateNewPage();
			if(ret == false)
			{
				return true;
			}
			this->freePositionHead.pageIndex = this->getPageNumber()-1;
			this->freePositionHead.chunkIndex = 0;

		}
		return false;
	}
	inline bool isEmpty(void)
	{
		return this->elementNumber==0;
	}
};

